﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Text;
using System.Net;
using System.Security.Cryptography;
using UnityEngine;

public static class UtilFunc
{
    public static int ConvertStructToBytes(object objStruct, byte[] buffer, int startIndex)
    {
        int size = Marshal.SizeOf(objStruct);
        IntPtr ipStruct = Marshal.AllocHGlobal(size);
        Marshal.StructureToPtr(objStruct, ipStruct, false);
        Marshal.Copy(ipStruct, buffer, startIndex, size);
        Marshal.FreeHGlobal(ipStruct);

        return size;
    }

    public static T ConvertBytesToStruct<T>(byte[] datas)
    {
        return ConvertBytesToStruct<T>(datas, 0);
    }

    public static T ConvertBytesToStruct<T>(byte[] datas, int offset)
    {
        int size = Marshal.SizeOf(typeof(T));

        if (datas.Length < size)
        {
            return default(T);
        }

        System.IntPtr ipSturct = Marshal.AllocHGlobal(size);
        Marshal.Copy(datas, offset, ipSturct, size);
        T objStruct = (T)Marshal.PtrToStructure(ipSturct, typeof(T));
        Marshal.FreeHGlobal(ipSturct);
        return objStruct;
    }

    public static List<int> Str2IntList(string str)
    {
        if (str == null || str == string.Empty)
        {
            return null;
        }

        string[] ss = str.Split(new char[] { ',' }, System.StringSplitOptions.RemoveEmptyEntries);
        List<int> ret = new List<int>(ss.Length);

        try
        {
            for (int i = 0; i < ss.Length; i++)
            {
                int n = int.Parse(ss[i]);
                ret.Add(n);
            }
        }
        catch (System.FormatException)
        {
            //LuaInterface.Debugger.LogError("String {0} parse to int list error", str);
        }

        return ret;
    }

    public static List<float> Str2FloatList(string str)
    {
        if (str == null || str == string.Empty)
        {
            return null;
        }

        string[] ss = str.Split(new char[] { ',' }, System.StringSplitOptions.RemoveEmptyEntries);
        List<float> ret = new List<float>(ss.Length);

        try
        {
            for (int i = 0; i < ss.Length; i++)
            {
                float n = float.Parse(ss[i]);
                ret.Add(n);
            }
        }
        catch (System.FormatException)
        {
            //LuaInterface.Debugger.LogError("String {0} parse to int list error", str);
        }

        return ret;
    }

    public static string IntList2str(List<int> list)
    {
        if (list.Count <= 0)
        {
            return string.Empty;
        }

        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < list.Count - 1; i++)
        {
            sb.Append(list[i]);
            sb.Append(",");
        }

        sb.Append(list[list.Count - 1]);
        return sb.ToString();
    }

    public static T DeSerializer<T>(string path, Encoding code)
    {
        using (TextReader reader = new StreamReader(path, code))
        {
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            StringReader stringReader = new StringReader(reader.ReadToEnd());
            XmlTextReader xmlReader = new XmlTextReader(stringReader);
            T data = (T)serializer.Deserialize(xmlReader);
            xmlReader.Close();
            stringReader.Close();
            reader.Close();

            return data;
        }
    }

    public static T DeSerializer<T>(string path)
    {
        string str = UnGfx.LoadTextAsset(path);
        XmlSerializer serializer = new XmlSerializer(typeof(T));
        StringReader stringReader = new StringReader(str);
        XmlTextReader xmlReader = new XmlTextReader(stringReader);
        T data = (T)serializer.Deserialize(xmlReader);
        xmlReader.Close();
        stringReader.Close();
        return data;
    }

    public static void Serializer<T>(T data, string path, Encoding code)
    {
        using (StringWriter sw = new StringWriter())
        {
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            serializer.Serialize(sw, data);

            TextWriter textWriter = new StreamWriter(path, false, code);
            textWriter.Write(sw.ToString());
            textWriter.Flush();
            textWriter.Close();
        }
    }

    public static void Serializer<T>(T data, string path)
    {
        Serializer<T>(data, path, Encoding.UTF8);
    }

    public static long TimeStamp()
    {
        System.DateTime timeStamp = new System.DateTime(1970, 1, 1);
        long t = (System.DateTime.UtcNow.Ticks - timeStamp.Ticks) / 10000000;
        return t;
    }

    public static int F2I(float f)
    {
        return (int)f;
    }

    public static string BytesToHexString(byte[] src)
    {
        StringBuilder sb = new StringBuilder("");

        if (src == null || src.Length <= 0)
        {
            return null;
        }

        for (int i = 0; i < src.Length; i++)
        {
            int v = src[i] & 0xFF;
            sb.Append(v.ToString("X2"));
        }

        return sb.ToString();
    }

    public static byte[] StringToBytes(string hexString)
    {
        hexString = hexString.Replace(" ", "");

        if ((hexString.Length % 2) != 0)
        {
            hexString += " ";
        }

        byte[] bs = new byte[hexString.Length / 2];

        for (int i = 0; i < bs.Length; i++)
        {
            bs[i] = System.Convert.ToByte(hexString.Substring(i * 2, 2), 16);
        }

        return bs;
    }

    public static bool IsConnection()
    {
        //外网
        WebRequest request = HttpWebRequest.Create("http://www.baidu.com");
        request.Method = "HEAD";
        WebResponse resp = null;

        try
        {
            resp = request.GetResponse();
        }
        catch
        {
            resp = null;
        }

        return resp != null;
    }

    public static string SplitFileName(string path)
    {
        int pos = path.LastIndexOf("/");

        if (pos <= 0)
        {
            pos = path.LastIndexOf("\\");
        }

        if (pos > 0 && pos + 1 < path.Length)
        {
            path = path.Substring(pos + 1);
        }

        return path;
    }

    public static string RemoveCloneString(string name)
    {
        int pos = name.IndexOf("(Clone)");

        if (pos > 0)
        {
            name = name.Substring(0, pos);
        }

        return name;
    }

    private static string GetMd5Hash(string name)
    {
        MD5 md5Hash = MD5.Create();
        Stream stream = File.Open(name, FileMode.Open, FileAccess.Read, FileShare.Read);
        byte[] data = md5Hash.ComputeHash(stream);
        StringBuilder sBuilder = new StringBuilder();

        for (int i = 0; i < data.Length; i++)
        {
            sBuilder.Append(data[i].ToString("x2"));
        }

        stream.Close();
        return sBuilder.ToString();
    }

    //string ReadBinaryFile(string name)
    //{
    //    using (FileStream fs = new FileStream(name, FileMode.Open, FileAccess.Read))
    //    {
    //        BinaryReader br = new BinaryReader(fs);

    //    }
    //}

    public static string Substring(string str, char c)
    {
        int pos = str.IndexOf(c);
        return pos > 0 ? str.Substring(0, pos) : str;
    }

    //public static string Format(string format, params object[] args)
    //{
    //    StringBuilder sb = StringBuilderCache.Acquire();
    //    sb.AppendFormat(format, args);
    //    return StringBuilderCache.GetStringAndRelease(sb);
    //}
    /// <summary>
    /// 判断点是否在多边形内.
    /// ----------原理----------
    /// 注意到如果从P作水平向左的射线的话，如果P在多边形内部，那么这条射线与多边形的交点必为奇数，
    /// 如果P在多边形外部，则交点个数必为偶数(0也在内)。
    /// </summary>
    /// <param name="checkPoint">要判断的点</param>
    /// <param name="polygonPoints">多边形的顶点</param>
    /// <returns></returns>
    public static bool IsInPolygon(Vector2 checkPoint, List<Vector2> polygonPoints)
    {
        bool inside = false;
        int pointCount = polygonPoints.Count;
        Vector3 p1, p2;
        for (int i = 0, j = pointCount - 1; i < pointCount; j = i, i++)//第一个点和最后一个点作为第一条线，之后是第一个点和第二个点作为第二条线，之后是第二个点与第三个点，第三个点与第四个点...
        {
            p1 = polygonPoints[i];
            p2 = polygonPoints[j];
            if (checkPoint.y < p2.y)
            {//p2在射线之上
                if (p1.y <= checkPoint.y)
                {//p1正好在射线中或者射线下方
                    if ((checkPoint.y - p1.y) * (p2.x - p1.x) > (checkPoint.x - p1.x) * (p2.y - p1.y))//斜率判断,在P1和P2之间且在P1P2右侧
                    {
                        //射线与多边形交点为奇数时则在多边形之内，若为偶数个交点时则在多边形之外。
                        //由于inside初始值为false，即交点数为零。所以当有第一个交点时，则必为奇数，则在内部，此时为inside=(!inside)
                        //所以当有第二个交点时，则必为偶数，则在外部，此时为inside=(!inside)
                        inside = (!inside);
                    }
                }
            }
            else if (checkPoint.y < p1.y)
            {
                //p2正好在射线中或者在射线下方，p1在射线上
                if ((checkPoint.y - p1.y) * (p2.x - p1.x) < (checkPoint.x - p1.x) * (p2.y - p1.y))//斜率判断,在P1和P2之间且在P1P2右侧
                {
                    inside = (!inside);
                }
            }
        }
        return inside;
    }
}